package com.me.libgdx_test;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;

public class ClassUnlockablePrototypes {

	private static ClassLogDisplay logger;
	private UnlockFactory factory_values;
	private static Object lock = new Object();
	
	ClassUnlockablePrototypes(){
		logger = new ClassLogDisplay("ClassUnlockablePrototypes");
		logger.print("ClassUnlockablePrototypes init");
	}
	
	public UnlockFactory get_factory(){
		logger.print("Returning Factory");
		return factory_values;
	}
	
	public void set_factory(UnlockFactory factory_values){
		this.factory_values = factory_values;
	}
	
	//This holds the json contructor info as it is received/sent to the server
	public static class UnlockFactory {

	   protected ArrayList<UnlockPrototype> classes;
	   protected ArrayList<UnlockPrototype> races;
	   protected ArrayList<UnlockPrototype> levels;
	   protected ArrayList<UnlockPrototype> spells;
	   protected ArrayList<UnlockUpgradePrototype> upgrades;
	   protected ArrayList<UnlockPlayerPrototype> player_assets;
	   protected CopyOnWriteArrayList<UnlockLevelPrototype> history;
	   protected ArrayList<UnlockPrototype> custom_character_items;
	   protected ArrayList<UnlockCustomPlayerPrototype> current_custom_character;
	   private int[] dungeon_completes = new int[]{1,3,4,5,7,8,9,10,10,11,12,14,15,16,18,20,20,20,20,20};
	   
	   public ArrayList<UnlockPrototype> get_classes(){
		   return classes;
	   }
	   public boolean get_class_unlocked(int id){
		   for(UnlockPrototype player_class: classes){
			   if(player_class.value == id){
				   return true;
			   }
		   }
		   return false;
	   }
	   public void unlock_class(int value){
		   logger.print("Class: " + value + " unlocked");
		   UnlockPrototype unlocker = new UnlockPrototype();
		   unlocker.value = value;
		   if(!classes.contains(unlocker)){
			   classes.add(unlocker);
		   }
	   }
	   public ArrayList<UnlockPrototype> get_races(){
		   return races;
	   }
	   public int[] get_dungeon_completes(){
		   return dungeon_completes;
	   }
	   public int current_completes(int level){
		   int current_completes = 0;
		   for(UnlockLevelPrototype ledger : history){
			   //logger.print("Level: " + String.valueOf(ledger.player_level));
			   //logger.print("Completed: " + String.valueOf(ledger.completed));
			   if(ledger.player_level == level && ledger.completed){
				   current_completes++;
			   }
		   }
		   //logger.print("Current Completes: " + current_completes);
		   return current_completes;
	   }
	   public boolean level_unlocked(int level){
		   return current_completes(level) >= dungeon_completes[level];
	   }
	   public boolean level_beaten(int player_level, int player_class){
		   for(UnlockLevelPrototype ledger:history){
			   if(ledger.player_class == player_class && ledger.player_level == player_level){
				   if(ledger.completed){
					   return true;
				   }else{
					   return false;
				   }
			   }
		   }
		   return false;
	   }
	   public void check_level_unlock(ClassDungeonRace[] raceObjects){
		   int current_level = 0;
		   boolean level_unlocked, race_unlocked;
		   while(level_unlocked(current_level)){
			   current_level++;
			   level_unlocked = false; 
			   race_unlocked = false;
			   for(UnlockPrototype level : levels){
				   if(level.value == current_level){
					   level_unlocked = true;
				   }
			   }
			   if(!level_unlocked){
				   UnlockPrototype unlock = new UnlockPrototype();
				   unlock.value = current_level;
				   levels.add(unlock);
			   }
			   //Go through the race objects
			   //if a race object == the current level
			   //and it isnt in the prototype, add it
			   //for(ClassDungeonRace raceObject : raceObjects){
			   for(int i = 0; i < raceObjects.length; i++){   
				   if(raceObjects[i].unlock_level == current_level){
					   for(UnlockPrototype race : races){
						   if(race.value == i){
							   race_unlocked = true;
						   }
					   }
					   if(!race_unlocked){
						   UnlockPrototype unlock = new UnlockPrototype();
						   unlock.value = i;
						   races.add(unlock);
					   }
				   }
			   }
		   }
	   }
	   public ArrayList<UnlockPrototype> get_levels(){
		   return levels;
	   }
	   public ArrayList<UnlockPrototype> get_spells(){
		   return spells;
	   }
	   public boolean get_spell_unlocked(int id){
		   logger.print("Looking for: " + id);
		   for(UnlockPrototype spell: spells){
			   logger.print("Searching: " + spell.value);
			   if(spell.value == id){
				   logger.print("Found: " + spell.value);
				   return true;
			   }
		   }
		   return false;
	   }
	   public void bank_loan(int unlock_level){
		   
		   logger.print("Unlock Level: " + unlock_level);
		   logger.print("Gold Before Loan: " + player_assets.get(0).honor);
		   logger.print("Honor Before Loan: " + player_assets.get(0).gold);
		   
		   ClassUnlockCost unlock = new ClassUnlockCost(unlock_level);
		   player_assets.get(0).honor += unlock.honor;
		   player_assets.get(0).gold += (unlock.gold*2);

		   logger.print("Gold After Loan: " + player_assets.get(0).honor);
		   logger.print("Honor After Loan: " + player_assets.get(0).gold);
	   }
	   public void unlock_spell(int value){
		   logger.print("unlock_spell");
		   logger.print("Spell: " + value + " unlocked");
		   UnlockPrototype unlocker = new UnlockPrototype();
		   unlocker.value = value;
		   //spells.clear();
		   spells.add(unlocker);
	   }
	   public ArrayList<UnlockUpgradePrototype> get_upgrades(){
		   return upgrades;
	   }
	   public int get_upgrade_at_id(int id){
		   //logger.print("Finding upgrade: " + id);
		   for(UnlockUpgradePrototype upgrade: upgrades){
			   if(upgrade.id == id){
				   //logger.print("Found level: " + upgrade.level);
				   return upgrade.level;
			   }
		   }
		   return 0;
	   }
	   public void add_end_level_info(int player_class, int player_level, ClassScoreHolder score, ClassDungeonRace[] raceObjects){
		   
		   //This function can be called twice sometimes for some reason
		   int level_before = get_current_level();
		   player_assets.get(0).gold += score.ending_gold;
		   player_assets.get(0).deaths += score.ending_deaths;
		   player_assets.get(0).kills += score.ending_kills;
		   player_assets.get(0).exp += score.get_final_score();
		   int level_after = get_current_level() + (score.medal_held()?1:0);
		   player_assets.get(0).honor += level_after - level_before;
		   //synchronized(lock){
			   add_level_history(player_class, player_level, (int) score.get_final_score(), score.win_bonus>0);
		   //}
		   check_level_unlock(raceObjects);
		   
	   }
	   public void make_purchase(ClassUnlockCost cost){
		   
		   logger.print("My Gold: " + player_assets.get(0).gold + " Gold Cost: " + cost.gold);
		   logger.print("My Honor: " + player_assets.get(0).honor + " Gold Honor: " + cost.honor);
		   
		   if(cost.gold <= player_assets.get(0).gold 
				   && cost.honor <= player_assets.get(0).honor){
			   player_assets.get(0).honor -= cost.honor;
			   player_assets.get(0).gold -= cost.gold;
		   }
	   }
	   public boolean check_purchase(ClassUnlockCost cost){
		   logger.print("My Gold: " + player_assets.get(0).gold + " Gold Cost: " + cost.gold);
		   logger.print("My Honor: " + player_assets.get(0).honor + " Gold Honor: " + cost.honor);
		   
		   if(cost.gold <= player_assets.get(0).gold && cost.honor <= player_assets.get(0).honor){
			   return true;
		   }
		   return false;
	   }
	   public void set_player_info(String player_detail, int value){
		   if(player_detail.toLowerCase().equals("honor")){
			   player_assets.get(0).honor = value;
		   }
		   if(player_detail.toLowerCase().equals("gold")){
			   player_assets.get(0).gold = value;
		   }
		   if(player_detail.toLowerCase().equals("deaths")){
			   player_assets.get(0).deaths = value;
		   }
		   if(player_detail.toLowerCase().equals("kills")){
			   player_assets.get(0).kills = value;
		   }
		   if(player_detail.toLowerCase().equals("exp")){
			   player_assets.get(0).exp = value;
		   }
	   }
	   public int get_player_info(String player_detail){
		   if(player_detail.toLowerCase().equals("honor")){
			   return player_assets.get(0).honor;
		   }
		   if(player_detail.toLowerCase().equals("gold")){
			   return player_assets.get(0).gold;
		   }
		   if(player_detail.toLowerCase().equals("deaths")){
			   return player_assets.get(0).deaths;
		   }
		   if(player_detail.toLowerCase().equals("kills")){
			   return player_assets.get(0).kills;
		   }
		   /*if(player_detail.toLowerCase().equals("level")){
			   return player_assets.get(0).level;
		   }*/
		   if(player_detail.toLowerCase().equals("exp")){
			   return player_assets.get(0).exp;
		   }
		   return -1;
	   }
	   public Point get_level_history(int player_level, int player_class){
		   for(UnlockLevelPrototype level_history:history){
			   if(level_history.player_class == player_class && level_history.player_level == player_level){
				   return new Point(level_history.score,level_history.completed?1:0);
			   }
		   }
		   return new Point(-1,-1);
	   }
	   public void add_level_history(int player_class, int player_level, int player_score, boolean completed){
		   boolean not_found = true;
		   for(UnlockLevelPrototype level_history:history){
			   if(level_history.player_class == player_class && level_history.player_level == player_level){
				   not_found = false;
				   if((!level_history.completed && completed) || (level_history.completed == completed && level_history.score < player_score)){
					   if(!level_history.completed && completed){
						   player_assets.get(0).honor++;
					   }
					   //We need to remove the old versions of the completes so a class doesn't complete the same level twice
					   history.remove(level_history);
					   
					   UnlockLevelPrototype unlock_object = new UnlockLevelPrototype();
					   unlock_object.completed = completed;
					   unlock_object.player_class = player_class;
					   unlock_object.player_level = player_level;
					   unlock_object.score = player_score;
					   history.add(unlock_object);
					   break;
				   }
			   }
		   }
		   if(not_found){
			   if(completed){
				   player_assets.get(0).honor++;
			   }
			   UnlockLevelPrototype unlock_object = new UnlockLevelPrototype();
			   unlock_object.completed = completed;
			   unlock_object.player_class = player_class;
			   unlock_object.player_level = player_level;
			   unlock_object.score = player_score;
			   history.add(unlock_object);
		   }
	   }
	   public void unlock_upgrade(int id){
		   logger.print("Upgrade: " + id + " unlocked");
		   for(UnlockUpgradePrototype upgrade: upgrades){
			   if(upgrade.id == id){
				   logger.print("Old level: " + upgrade.level);
				   upgrade.level++;
				   logger.print("New level: " + upgrade.level);
			   }
		   }
	   }
	   public ArrayList<UnlockPlayerPrototype> get_player_assets(){
		   return player_assets;
	   }
	   public CopyOnWriteArrayList<UnlockLevelPrototype> get_history(){
		   return history;
	   }
	   public ArrayList<UnlockPrototype> get_custom_character_items(){
		   return custom_character_items;
	   }
	   public ArrayList<UnlockCustomPlayerPrototype> get_current_custom_character(){
		   return current_custom_character;
	   }
	   
	   public void print_data(){
		   for(UnlockPrototype unlockable: classes){
			   logger.print("Class: " + unlockable.value);
		   }
		   for(UnlockPrototype unlockable: races){
			   logger.print("Race: " + unlockable.value);
		   }
		   for(UnlockPrototype unlockable: levels){
			   logger.print("Level: " + unlockable.value);
		   }
		   for(UnlockPrototype spell: spells){
			   logger.print("Spell_id: " + spell.value);
		   }
		   for(UnlockUpgradePrototype unlockable: upgrades){
			   logger.print("Upgrade_id: " + unlockable.id);
			   logger.print("Upgrade_level: " + unlockable.level);
		   }
		   for(UnlockPlayerPrototype unlockable: player_assets){
			   logger.print("Honor: " + unlockable.honor);
			   logger.print("Gold: " + unlockable.gold);
			   logger.print("Deaths: " + unlockable.deaths);
			   logger.print("Kills: " + unlockable.kills);
			   logger.print("Exp: " + unlockable.exp);
		   }
		   synchronized(lock){
			   for(UnlockLevelPrototype unlockable: history){
				   logger.print("History Level: " + unlockable.player_level);
				   logger.print("History Class: " + unlockable.player_class);
				   logger.print("History Score: " + unlockable.score);
				   logger.print("History Completed: " + unlockable.completed);
			   }
		   }
		   for(UnlockPrototype unlockable: custom_character_items){
			   logger.print("Unlocked Item: " + unlockable.value);
		   }
		   for(UnlockCustomPlayerPrototype unlockable: current_custom_character){
			   logger.print("Head: " + unlockable.head);
			   logger.print("Torso: " + unlockable.torso);
			   logger.print("Legs: " + unlockable.legs);
		   }
	   }
		public int get_current_level(){
			int i = 1;
			while(((i*i)*500 + i*500)< player_assets.get(0).exp){
				i++;
			}
			return i-1;
		}
	}
	
	public static class UnlockLevelPrototype {
		   public int player_level;
		   public int player_class;
		   public int score;
		   public boolean completed;
	}
	
	public static class UnlockUpgradePrototype {
		   public int id;
		   public int level;
	}
	
	public static class UnlockPlayerPrototype {
		   public int honor;
		   public int gold;
		   public int deaths;
		   public int kills;
		   public int exp;
	}
	
	public static class UnlockCustomPlayerPrototype {
		   public int head;
		   public int torso;
		   public int legs;
	}
	
	public static class UnlockPrototype {
		   public int value;
	}
}
